use crate::List::{Cons, Nil};
use std::ops::Deref;
use std::rc::Rc;

/*不通过
enum List {
    Cons(i32, List),
    Nil,
}
*/

#[derive(Debug)]
enum List {
    Cons(i32, Rc<List>),
    Nil,
}


fn rc_demo() {
    let a = Rc::new(Cons(5, Rc::new(Cons(10, Rc::new(Nil)))));
    /* 没有引用计数，被move了。
    let b = Cons(3, Box::new(a));
    let c = Cons(2, Box::new(a));
    */
    let b = Cons(3, Rc::clone(&a));
    let c = Cons(2, Rc::clone(&a));
}


struct MyBox<T>(T);

// 实现new和Deref两个trait，可以成为box类型。用来将不确定类型的数据
// 保存在堆上。
impl<T> MyBox<T> {
    fn new(x: T) -> MyBox<T> {
        MyBox(x)
    }
}

impl<T> Deref for MyBox<T> {
    type Target = T;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}


#[derive(Debug)]
struct CustomSP {
    data: String,
}

impl Drop for CustomSP {
    fn drop(&mut self) {
        println!("Dropping `{}`", self.data);
    }
}

fn main() {
    let b = Box::new(5);
    println!("b: {}!", b);

    // let list = Cons(1, Box::new(Cons(2, Box::new(Cons(3, Box::new(Nil))))));
    // println!("list: {:?}", list);

    rc_demo();


    let y = MyBox::new(5);
    assert_eq!(5, *y); // *(y.deref())


    // drop，超出作用域被清理前调用的。
    {
        let c = CustomSP{data: String::from("my world")};
        println!("created of {:?}", c);
    }
    let d = CustomSP{data: String::from("my name")};
    let e = CustomSP{data: String::from("my name2")};
    let f = CustomSP{data: String::from("my name3")};
    println!("{:?}, {:?}", e, f);
    drop(d);
    println!("end");
}
